﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Configuration;
using Spider.Util;
using System.IO;
using System.Reflection;

namespace Spider.Network
{
    public sealed class Panda : IDisposable
    {
        private bool disosed = false;
        private PandaConfiguration config = null;
        private Socket srv = null;
        public Panda(string configFileName)
        {
            Config(configFileName);
        }
        public Panda(Encoding encoding, string ip = "127.0.0.1", int port = 9999, int backlog = 100, int bufferSize = 102400, ProtocolType protocol = ProtocolType.IP)
        {
            PandaConfiguration config = new PandaConfiguration();
            config.IP = ip;
            config.Port = port;
            config.Backlog = backlog;
            config.BufferSize = bufferSize;
            config.Protocol = protocol;
            config.Encoding = encoding == null ? Encoding.UTF8 : encoding;
            Initiatie(config);
        }
        public void Start()
        {
            while (!disosed)
            {
                Socket client = srv.Accept();
                DoAction(client);
            }
        }
        private void DoAction(Socket client)
        {
            byte[] bytes = new byte[config.BufferSize];
            client.BeginReceive(bytes, 0, bytes.Length, SocketFlags.None, ar2 =>
            {
                SocketError errorCode = SocketError.Success;
                client.EndReceive(ar2, out errorCode);
                if (errorCode != SocketError.Success)
                {
                    Logger.ErrorFormat("Receive Error: {0}", errorCode);
                    client.Close();
                }
                else
                {
                    string message = config.Encoding.GetString(bytes);
                    Logger.DebugFormat("Receive:{0}", message);
                    //处理请求.......
                    byte[] buffer = config.Encoding.GetBytes("send message ok!");
                    client.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, ar3 =>
                    {
                        SocketError errorCode2 = SocketError.Success;
                        client.EndSend(ar3, out errorCode2);
                        client.Close();
                        if (errorCode2 != SocketError.Success)
                        {
                            Logger.ErrorFormat("Receive Error: {0}", errorCode2);
                        }
                    }, null);
                }
            }, null);
        }
        private void Initiatie(PandaConfiguration config)
        {
            this.config = config;
            IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(config.IP), config.Port);
            srv = new Socket(AddressFamily.InterNetwork, SocketType.Stream, config.Protocol);
            srv.Bind(endPoint);
            srv.Listen(config.Backlog);
        }
        public void Close()
        {
            Dispose();
        }
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        private void Config(string configFileName)
        {
            if (string.IsNullOrEmpty(configFileName))
            {
                throw new ArgumentException("configFileName");
            }
            PandaConfiguration config = null;
            string path = AppDomain.CurrentDomain.BaseDirectory+"\\"+configFileName;
            using (StreamReader sr = new StreamReader(path))
            {
                config = PandaFormater.Deserialize(sr.ReadToEnd());
            }
            if (!disosed && srv != null)
            {
                srv.Close();
            }
            Initiatie(config);
        }
        private void Dispose(bool disposing)
        {
            if (!disosed && srv != null)
            {
                if (disposing)
                {
                    this.config = null;
                }
                srv.Close();
                disosed = true;
            }
        }
        ~Panda()
        {
            Dispose(false);
        }
    }
}
